home *** CD-ROM | disk | FTP | other *** search
- #include <Palettes.h>
- #include <AppleEvents.h>
-
- #include "GameShell.h"
- #include "assert_mac.h"
- #include "GameShellMonitor.h"
-
- #include "Compat.h"
- #include "QDUtils.h"
- #include "GameUtils.h"
-
- // ---------------------------------------------------------------------------
-
- #define USE_GETNEXTEVENT
-
- // ---------------------------------------------------------------------------
-
- enum {
- kMaxBlackoutWindows = 10,
-
- kAppleMenuID = 128
- };
-
- typedef struct {
- GDHandle primaryDevice;
- WindowPtr mainWindow;
- WindowPtr backdropWindow;
- WindowPtr blackoutWindows[kMaxBlackoutWindows];
- long numBlackoutWindows;
-
- void (*mainWindowUpdateFunction)();
- void (*menuHandlerFunction)(long);
- void (*mouseHandlerFunction)(CP_Point*);
- void (*keyHandlerFunction)(long);
- void (*idleHandlerFunction)();
-
- CP_Rect windowBounds;
- CP_Rect windowSize;
-
- short useMenuBar; // true or false
- short useBlackout; // true or false
- short useBackdrop; // true or false
- short usingMainMonitor; // true or false
- short primaryDeviceOrigDepth; // 1 to 32
- short _longwordPadding;
- } GameShellGlobals;
-
- static GameShellGlobals sPrivateShellData;
- static long sGameShellQuitFlag;
-
- // ---------------------------------------------------------------------------
-
- static void GameShellHandleMouse(EventRecord *theEvent);
- static void GameShellHandleKeys(EventRecord *theEvent);
- static void GameShellHandleActivate(EventRecord *theEvent);
- static void GameShellHandleUpdate(EventRecord *theEvent);
-
- static void GameShellHandleMenus(Point globalLoc);
- static void GameShellHandleIdle();
- static void GameShellHandleOSEvent(EventRecord *theEvent);
- static void GameShellHandleResume();
- static void GameShellHandleSuspend();
-
- // ===========================================================================
-
- CP_Window_Ref GameShellGetMainWindow()
- {
- ASSERT(sPrivateShellData.mainWindow != NULL);
-
- return(sPrivateShellData.mainWindow);
- } // END GameShellGetMainWindow
-
- // ---------------------------------------------------------------------------
-
- CP_OutputDevice_Ref GameShellGetOutputDevice() {
- ASSERT(sPrivateShellData.primaryDevice != NULL);
-
- return(sPrivateShellData.primaryDevice);
- } // END GameShellGetOutputDevice
-
- // ---------------------------------------------------------------------------
-
- void GameShellGetWindowCoords(CP_Rect *globCoords)
- {
- ASSERT(!(globCoords == NULL));
-
- *globCoords = sPrivateShellData.windowBounds;
- } // END GameShellGetWindowCoords
-
- // ---------------------------------------------------------------------------
-
- void GameShellSetQuitFlag(long quitFlag) {
- ASSERT(sGameShellQuitFlag == true || sGameShellQuitFlag == false);
-
- sGameShellQuitFlag = quitFlag;
- } // END GameShellSetQuitFlag
-
- // ---------------------------------------------------------------------------
-
- OSErr GameShellInitialize(UserParameters *userInfo)
- /*
- Call this after initializing all your Mac toolbox routines, but
- pretty much before calling anything else.
-
- GameShellInitialize will setup its internal variables, and then
- setup the windows.
- */
- {
- GDHandle curDevice;
- long i;
-
- ASSERT(userInfo != NULL);
-
- CheckEnviron();
-
- SetRect(&sPrivateShellData.windowSize, 0, 0,
- userInfo->windowWidth, userInfo->windowHeight);
-
- // The default is a call to GameShellChooseMonitor. You
- // can change this to GameShellUserSelectMonitor if you wish.
- sPrivateShellData.primaryDeviceOrigDepth = GameShellChooseMonitor(
- &sPrivateShellData.primaryDevice, userInfo->preferredDepth,
- userInfo->minimumDepth, userInfo->windowWidth, userInfo->windowHeight);
-
- // No monitors with preferred or minimum depths found!
- if (sPrivateShellData.primaryDeviceOrigDepth == 0) {
- return(1);
- }
-
- // Handle menu bar hiding
- ASSERT(!(userInfo->useMenuBar != true && userInfo->useMenuBar != false));
- sPrivateShellData.useMenuBar = userInfo->useMenuBar;
-
- sPrivateShellData.usingMainMonitor = sPrivateShellData.primaryDevice ==
- GetMainDevice();
- HideMenuBar(false);
-
- // Handle menu bar initialization, if any
- if (userInfo->useMenuBar && userInfo->menuInitFunction != NULL)
- (*userInfo->menuInitFunction)();
- sPrivateShellData.menuHandlerFunction = userInfo->menuHandlerFunction;
-
- // Handle blacking out of other windows
- ASSERT(!(userInfo->useBlackout != true && userInfo->useBlackout != false));
- sPrivateShellData.useBlackout = userInfo->useBlackout;
-
- for (i = 0; i < kMaxBlackoutWindows; i++)
- sPrivateShellData.blackoutWindows[i] = NULL;
-
- sPrivateShellData.numBlackoutWindows = 0;
-
- if (sPrivateShellData.useBlackout == true) {
- curDevice = GetDeviceList();
-
- while (curDevice != NULL &&
- sPrivateShellData.numBlackoutWindows < kMaxBlackoutWindows) {
- // No blackout windows for primary monitor; it'll
- // be handled by both backdrop and main window
- if (curDevice != sPrivateShellData.primaryDevice) {
-
- sPrivateShellData.blackoutWindows[sPrivateShellData.numBlackoutWindows] =
- NewCWindow(NULL, &(**curDevice).gdRect, "\p", true,
- plainDBox, (WindowPtr)-1, false, sPrivateShellData.numBlackoutWindows);
- ASSERT(!(sPrivateShellData.blackoutWindows[sPrivateShellData.numBlackoutWindows]==NULL));
-
- SetPort(sPrivateShellData.blackoutWindows[sPrivateShellData.numBlackoutWindows]);
- FillRect(&sPrivateShellData.blackoutWindows[sPrivateShellData.numBlackoutWindows]->portRect,
- &qd.black);
-
- sPrivateShellData.numBlackoutWindows++;
- }
-
- curDevice = GetNextDevice(curDevice);
- }
- }
-
- // Handle backdrop window
- ASSERT(!(userInfo->useBackdrop != true && userInfo->useBackdrop != false));
- sPrivateShellData.useBackdrop = userInfo->useBackdrop;
- sPrivateShellData.backdropWindow = NULL;
-
- // Handle only if monitor is larger than main window (thus showing desktop).
- // If main window is the same size as the monitor, there's no need for a
- // backdrop window.
- if ((sPrivateShellData.useBackdrop) &&
- ((((**sPrivateShellData.primaryDevice).gdRect.right -
- (**sPrivateShellData.primaryDevice).gdRect.left) > userInfo->windowWidth)
- && (((**sPrivateShellData.primaryDevice).gdRect.bottom -
- (**sPrivateShellData.primaryDevice).gdRect.top) > userInfo->windowHeight))) {
-
- sPrivateShellData.backdropWindow = NewCWindow(NULL,
- &(**sPrivateShellData.primaryDevice).gdRect, "\p", true,
- plainDBox, (WindowPtr)-1, false, 0);
- ASSERT(!(sPrivateShellData.backdropWindow == NULL));
-
- SetPort(sPrivateShellData.backdropWindow);
- FillRect(&sPrivateShellData.backdropWindow->portRect, &qd.black);
- }
-
- // Handle main window
- sPrivateShellData.windowBounds = sPrivateShellData.windowSize;
- CenterRect(&sPrivateShellData.windowBounds,
- &(**sPrivateShellData.primaryDevice).gdRect);
- sPrivateShellData.mainWindow = NULL;
- sPrivateShellData.mainWindow = NewCWindow(NULL, &sPrivateShellData.windowBounds,
- "\p", true, plainDBox, (WindowPtr)-1, false, 0);
- ASSERT(!(sPrivateShellData.mainWindow == NULL));
-
- SetPort(sPrivateShellData.mainWindow);
- FillRect(&sPrivateShellData.mainWindow->portRect, &qd.black);
-
- // The main window updater & mouse handler functions are MANDATORY.
- // You must supply them.
- ASSERT(!(userInfo->mainWindowUpdateFunction == NULL));
- sPrivateShellData.mainWindowUpdateFunction = userInfo->mainWindowUpdateFunction;
- ASSERT(!(userInfo->mouseHandlerFunction == NULL));
- sPrivateShellData.mouseHandlerFunction = userInfo->mouseHandlerFunction;
-
- // These are optional
- sPrivateShellData.keyHandlerFunction = userInfo->keyHandlerFunction;
- sPrivateShellData.idleHandlerFunction = userInfo->idleHandlerFunction;
-
- sGameShellQuitFlag = false;
-
- return(noErr);
- } // END GameShellInitialize
-
- // ---------------------------------------------------------------------------
-
- void GameShellCleanup()
- {
- // Restore menu bar if necessary
- ShowMenuBar();
-
- // Restore depth if necessary
- if ((**(**sPrivateShellData.primaryDevice).gdPMap).pixelSize !=
- sPrivateShellData.primaryDeviceOrigDepth)
- SetDepth(sPrivateShellData.primaryDevice,
- sPrivateShellData.primaryDeviceOrigDepth, 1 << gdDevType, 1);
- } // END GameShellCleanup
-
- // ---------------------------------------------------------------------------
-
- void GameShellLoop()
- {
- EventRecord theEvent;
- short eventExists;
- short padding;
-
- while (!sGameShellQuitFlag) {
-
- #ifdef USE_GETNEXTEVENT
- eventExists = GetNextEvent(everyEvent, &theEvent);
- #else
- eventExists = WaitNextEvent(everyEvent, &theEvent, 2, NULL);
- #endif
-
- if (eventExists) {
- switch(theEvent.what) {
- case mouseDown: //case mouseUp:
- GameShellHandleMouse(&theEvent);
- break;
-
- case keyDown: case keyUp:
- GameShellHandleKeys(&theEvent);
- break;
-
- case activateEvt:
- GameShellHandleActivate(&theEvent);
- break;
-
- case updateEvt:
- GameShellHandleUpdate(&theEvent);
- break;
-
- case osEvt:
- GameShellHandleOSEvent(&theEvent);
- break;
-
- case kHighLevelEvent:
- break;
- }
- }
- else {
- // Handle idleness
- GameShellHandleIdle();
- }
- }
- } // END GameShellLoop
-
- // ---------------------------------------------------------------------------
-
- void GameShellHandleMouse(EventRecord *theEvent)
- /*
- This routine handles mouse clicks in the menu bar area (if menus
- are used) and in the main window's content area. All others are
- ignored.
- */
- {
- Rect menuBarRect;
-
- WindowPtr theWindow;
- short thePart;
-
- ASSERT(theEvent != NULL);
-
- thePart = FindWindow(theEvent->where, &theWindow);
- switch(thePart) {
- case inMenuBar:
- // If we're invoked, we assume that the menu bar's visible.
- if (sPrivateShellData.useMenuBar &&
- sPrivateShellData.menuHandlerFunction != NULL) {
- GameShellHandleMenus(theEvent->where);
- }
- break;
-
- case inContent:
- // Kind of tricky here. We also have to handle the menu bar...
-
- // Show menu bar ONLY if it's currently hidden AND
- // the user clicks in the area normally occupied by the menu bar.
- if (sPrivateShellData.useMenuBar && gMenuBarHidden) {
- GetMenuBarRect(&menuBarRect);
- if (PtInRect(theEvent->where, &menuBarRect))
- ShowMenuBar();
- }
-
- // User clicks in main window; call mouse handler.
- if (theWindow == sPrivateShellData.mainWindow) {
- SetPort(sPrivateShellData.mainWindow);
- GlobalToLocal(&theEvent->where);
- (*sPrivateShellData.mouseHandlerFunction)((CP_Point*)&theEvent->where);
- }
- break;
- }
- } // END GameShellHandleMouse
-
- // ---------------------------------------------------------------------------
-
- void GameShellHandleKeys(EventRecord *theEvent)
- {
- char theChar;
- char pad1, pad2, pad3;
-
- ASSERT(theEvent != NULL);
-
- theChar = theEvent->message & charCodeMask;
- // Call keydown handler if one is provided.
- if (sPrivateShellData.keyHandlerFunction != NULL)
- (*sPrivateShellData.keyHandlerFunction)((long)theChar);
- else {
- sGameShellQuitFlag = true;
- }
- } // END GameShellHandleKeys
-
- // ---------------------------------------------------------------------------
-
- void GameShellHandleActivate(EventRecord *theEvent)
- {
- WindowPtr theWindow;
-
- ASSERT(theEvent != NULL);
-
- theWindow = (WindowPtr)theEvent->message;
- ASSERT(!(theWindow == NULL));
-
- if (theEvent->modifiers & activeFlag != 0) {
- // Activate event
- SetPort(theWindow);
- }
- else {
- // Deactivate event
- }
- } // END GameShellHandleActivate
-
- // ---------------------------------------------------------------------------
-
- void GameShellHandleUpdate(EventRecord *theEvent)
- {
- GrafPtr savePort;
- WindowPtr theWindow;
-
- ASSERT(theEvent != NULL);
-
- theWindow = (WindowPtr)theEvent->message;
- ASSERT(theWindow != NULL);
-
- GetPort(&savePort);
- SetPort(theWindow);
-
- BeginUpdate(theWindow);
-
- if (theWindow == sPrivateShellData.mainWindow)
- (*sPrivateShellData.mainWindowUpdateFunction)();
- else {
- SetPort(theWindow);
- FillRect(&theWindow->portRect, &qd.black);
- SetPort(sPrivateShellData.mainWindow);
- }
-
- EndUpdate(theWindow);
-
- SetPort(savePort);
- } // END GameShellHandleUpdate
-
- // ---------------------------------------------------------------------------
-
- void GameShellHandleMenus(Point globalLoc)
- /*
- The user is expected to handle all menus and menu items
- except for those desk accessories and other junk in the
- Apple menu; we'll handle it for them (note the user still
- has to handle the About... item in the Apple Menu).
- */
- {
- long menuCode;
- short menuData;
- short padding;
- Str255 daName;
-
- menuCode = MenuSelect(globalLoc);
- if (menuCode == 0) return;
-
- // Yeah, unhilite it *now*. The menu handler function is
- // not expected to have to deal with this extraneous crap.
- HiliteMenu(0);
-
- // Menu bar has to be visible before getting an
- // inMenuBar mouse click, so we know it's visible...
- // Hide menu bar before calling menu item handler.
- if (!gMenuBarHidden)
- HideMenuBar(false);
-
- menuData = HiWord(menuCode);
-
- if (menuData == kAppleMenuID) {
- menuData = LoWord(menuCode);
- if (menuData > 1) {
- GetMenuItemText(GetMenuHandle(kAppleMenuID), menuData,
- daName);
- (void)OpenDeskAcc(daName);
- }
- else
- (*sPrivateShellData.menuHandlerFunction)(menuCode);
- }
- else
- (*sPrivateShellData.menuHandlerFunction)(menuCode);
- } // END GameShellHandleMenus
-
- // ---------------------------------------------------------------------------
-
- void GameShellHandleIdle()
- {
- Rect menuBarRect;
- Point mouseLoc;
-
- // Hide menu bar if currently shown and mouse not
- // in menu bar area.
- if (sPrivateShellData.useMenuBar && !gMenuBarHidden) {
- GetMenuBarRect(&menuBarRect);
- GetMouse(&mouseLoc);
- LocalToGlobal(&mouseLoc);
- if (!PtInRect(mouseLoc, &menuBarRect))
- HideMenuBar(false);
- }
-
- if (sPrivateShellData.idleHandlerFunction != NULL)
- (*sPrivateShellData.idleHandlerFunction)();
- } // END GameShellHandleIdle
-
- // ---------------------------------------------------------------------------
-
- void GameShellHandleOSEvent(EventRecord *theEvent)
- {
- ASSERT(!(theEvent == NULL));
-
- if (((theEvent->message >> 24) & 0x0FF) == suspendResumeMessage) {
- if (theEvent->message & resumeFlag != 0) {
- // Resume event
- GameShellHandleResume();
- }
- else {
- // Suspend event
- GameShellHandleSuspend();
- }
- }
- } // END GameShellHandleOSEvent
-
- // ---------------------------------------------------------------------------
-
- void GameShellHandleResume()
- {
- long i;
-
- // Show all windows; do the blackout windows first, if any
- if (sPrivateShellData.useBlackout) {
- for (i = 0; i < sPrivateShellData.numBlackoutWindows; i++) {
- ASSERT(sPrivateShellData.blackoutWindows[i] != NULL);
- ShowWindow(sPrivateShellData.blackoutWindows[i]);
- }
- }
-
- // Do backdrop
- if (sPrivateShellData.useBackdrop &&
- sPrivateShellData.backdropWindow != NULL)
- ShowWindow(sPrivateShellData.backdropWindow);
-
- ShowWindow(sPrivateShellData.mainWindow);
- SelectWindow(sPrivateShellData.mainWindow);
- SetPort(sPrivateShellData.mainWindow);
-
- HideMenuBar(false);
- } // END GameShellHandleResume
-
- // ---------------------------------------------------------------------------
-
- void GameShellHandleSuspend()
- {
- long i;
-
- // Hide all windows; first do the blackout windows
- if (sPrivateShellData.useBlackout) {
- for (i = 0; i < sPrivateShellData.numBlackoutWindows; i++) {
- ASSERT(sPrivateShellData.blackoutWindows[i] != NULL);
- HideWindow(sPrivateShellData.blackoutWindows[i]);
- }
- }
-
- // Now do backdrop, if any
- if (sPrivateShellData.useBackdrop &&
- sPrivateShellData.backdropWindow != NULL) {
- HideWindow(sPrivateShellData.backdropWindow);
- }
-
- // Now do main window
- HideWindow(sPrivateShellData.mainWindow);
-
- ShowMenuBar();
- } // END GameShellHandleSuspend